<?php
/**
 * Created by PhpStorm.
 * Author: sitewang@aliyun.com
 * CreateTime: 2022/11/01 2022/11/1
 * Blog：www.myblogs.xyz
 */

namespace app\common\service;

class AliPayService
{
    protected $app_id = ''; // 支付宝AppId
    protected $applet_id = ''; // 小程序AppId
    protected $seller = ''; // 收款人账号
    protected $private_key = ''; // 支付宝商户私钥
    protected $public_key = ''; // 支付宝公钥
    protected $appCertPath = ''; // APP应用证书路径
    protected $appletCertPath = ''; // 小程序应用证书路径
    protected $aliPayCertPath = ''; // 支付宝公钥证书路径
    protected $rootCertPath = ''; // 支付宝根证书路径

    public function __construct()
    {
        $payment_data = config('payment.ali_pay');
        $this->app_id = $payment_data['app_id'];
        $this->private_key = app_path() . 'certs/private_key.pem';
        $this->public_key =  app_path() . 'certs/public_key.pem';
        $this->aliPayCertPath =  app_path() . $payment_data['app_cert_public_key'];
        $this->rootCertPath =  app_path() . $payment_data['alipay_root_cert'];
        $this->appCertPath =  app_path() . 'certs/appCertPublicKey_' . $this->app_id . '.crt';
    }

    /**
     * APP支付宝支付
     * @param $subject
     * @param $order_code
     * @param $money
     * @param $notify_url
     * @return string
     */
    public function aliPayApp($param)
    {
        import('alipay.aop.AopCertClient');
        import('alipay.aop.request.AlipayTradeAppPayRequest');

        $aop = new \AopCertClient();
        $aop->gatewayUrl = 'https://openapi.alipay.com/gateway.do';
        $aop->appId = $this->app_id;
        $aop->rsaPrivateKeyFilePath = $this->private_key;
        $aop->signType = 'RSA2';
        $aop->isCheckAlipayPublicCert = true;
        $aop->alipayrsaPublicKey = $aop->getPublicKey($this->aliPayCertPath);
        $aop->appCertSN = $aop->getCertSN($this->appCertPath);//调用getCertSN获取证书序列号
        $aop->alipayRootCertSN = $aop->getRootCertSN($this->rootCertPath);//调用getRootCertSN获取支付宝根证书序列号

        $object = new \stdClass();
        $object->out_trade_no = $param['order_code'];
        $object->total_amount = floatval($param['money']);
        $object->subject = $param['subject'];
        $object->product_code = 'QUICK_MSECURITY_PAY';
        $object->time_expire = date('Y-m-d H:i:s', $param['time_expire']);
        $json = json_encode($object);

        $request = new \AlipayTradeAppPayRequest();
        $request->setNotifyUrl($param['notify_url']);
        $request->setBizContent($json);

        $result = $aop->sdkExecute($request);
        return $result;
    }

    /**
     * PC端支付宝支付
     * @param $subject
     * @param $order_code
     * @param $money
     * @param $notify_url
     * @param $return_url
     * @return string|\提交表单HTML文本
     * @throws \Exception
     */
    public function aliPayWeb($param)
    {
        import('alipay.aop.AopCertClient');
        import('alipay.aop.request.AlipayTradePagePayRequest');

        $aop = new \AopCertClient();
        $aop->gatewayUrl = 'https://openapi.alipay.com/gateway.do';
        $aop->appId = $this->app_id;
        $aop->rsaPrivateKeyFilePath = $this->private_key;
        $aop->signType = 'RSA2';
        $aop->isCheckAlipayPublicCert = true;
        $aop->alipayrsaPublicKey = $aop->getPublicKey($this->aliPayCertPath);
        $aop->appCertSN = $aop->getCertSN($this->appCertPath);//调用getCertSN获取证书序列号
        $aop->alipayRootCertSN = $aop->getRootCertSN($this->rootCertPath);//调用getRootCertSN获取支付宝根证书序列号

        $object = new \stdClass();
        $object->out_trade_no = $param['order_code'];
        $object->total_amount = floatval($param['money']);
        $object->subject = $param['subject'];
        $object->product_code = 'FAST_INSTANT_TRADE_PAY';
        $object->time_expire = date('Y-m-d H:i:s', $param['time_expire']);
        $json = json_encode($object);

        $request = new \AlipayTradePagePayRequest();
        $request->setNotifyUrl($param['notify_url']);
        $request->setReturnUrl($param['return_url']);
        $request->setBizContent($json);
        $result = $aop->pageExecute($request);

        return $result;
    }

    /**
     * WAP端支付宝支付
     * @param $subject
     * @param $order_code
     * @param $money
     * @return string|\提交表单HTML文本
     * @throws \Exception
     */
    public function aliPayWap($param)
    {
        import('alipay.aop.AopCertClient');
        import('alipay.aop.request.AlipayTradeWapPayRequest');

        $aop = new \AopCertClient();
        $aop->gatewayUrl = 'https://openapi.alipay.com/gateway.do';
        $aop->appId = $this->app_id;
        $aop->rsaPrivateKeyFilePath = $this->private_key;
        $aop->signType = 'RSA2';
        $aop->isCheckAlipayPublicCert = true;
        $aop->alipayrsaPublicKey = $aop->getPublicKey($this->aliPayCertPath);
        $aop->appCertSN = $aop->getCertSN($this->appCertPath);//调用getCertSN获取证书序列号
        $aop->alipayRootCertSN = $aop->getRootCertSN($this->rootCertPath);//调用getRootCertSN获取支付宝根证书序列号

        $object = new \stdClass();
        $object->out_trade_no = $param['order_code'];
        $object->total_amount = floatval($param['money']);
        $object->subject = $param['subject'];
        $object->product_code = 'QUICK_WAP_WAY';
        $object->time_expire = date('Y-m-d H:i:s', $param['time_expire']);
        $json = json_encode($object);

        $request = new \AlipayTradeWapPayRequest();
        $request->setNotifyUrl($param['notify_url']);
        $request->setReturnUrl($param['return_url']);
        $request->setBizContent($json);

        $result = $aop->pageExecute($request);

        return $result;
    }

    /**
     * 订单退款
     * @param $order_code
     * @param $trade_code
     * @param $money
     * @param string $reason
     * @return bool
     * @throws \Exception
     */
    public function refund($order_code, $trade_code, $money, $reason = '订单退款')
    {
        /**
         * 调用支付宝接口。
         */
        import('alipay.aop.AopCertClient');
        import('alipay.aop.request.AlipayTradeRefundRequest');

        $aop = new \AopCertClient();
        $aop->gatewayUrl = 'https://openapi.alipay.com/gateway.do';
        $aop->appId = $this->app_id;
        $aop->rsaPrivateKeyFilePath = $this->private_key;
        $aop->signType = 'RSA2';
        $aop->isCheckAlipayPublicCert = true;
        $aop->alipayrsaPublicKey = $aop->getPublicKey($this->aliPayCertPath);
        $aop->appCertSN = $aop->getCertSN($this->appCertPath);//调用getCertSN获取证书序列号
        $aop->alipayRootCertSN = $aop->getRootCertSN($this->rootCertPath);//调用getRootCertSN获取支付宝根证书序列号

        $request = new \AlipayTradeRefundRequest();
        $content = [
            'out_trade_no'=>$trade_code,
            'refund_amount'=>$money,
            'refund_reason'=>$reason,
            'out_request_no'=>$order_code,
            'operator_id'=>'OP001',
            'store_id'=>'NJ_S_001',
            'terminal_id'=>'',
            'goods_detail'=>[]
        ];
        $request->setBizContent(json_encode($content));
        $result = $aop->execute($request);
        $responseNode = str_replace(".", "_", $request->getApiMethodName()) . "_response";
        $resultCode = $result->$responseNode->code;
        if (!empty($resultCode) && $resultCode == 10000){
            return true;
        }else{
            return false;
        }
    }

    /**
     * 支付宝转账
     * @param $order_code
     * @param $payee_account
     * @param $money
     * @return bool
     * @throws \Exception
     */
    public function transfer($order_code, $payee_account, $money)
    {
        /**
         * 调用支付宝接口。
         */
        import('alipay.aop.AopCertClient');
        import('alipay.aop.request.AlipayFundTransToaccountTransferRequest');

        $aop = new \AopCertClient();
        $aop->gatewayUrl = 'https://openapi.alipay.com/gateway.do';
        $aop->appId = $this->app_id;
        $aop->rsaPrivateKeyFilePath = $this->private_key;
        $aop->signType = 'RSA2';
        $aop->isCheckAlipayPublicCert = true;
        $aop->alipayrsaPublicKey = $aop->getPublicKey($this->aliPayCertPath);
        $aop->appCertSN = $aop->getCertSN($this->appCertPath);//调用getCertSN获取证书序列号
        $aop->alipayRootCertSN = $aop->getRootCertSN($this->rootCertPath);//调用getRootCertSN获取支付宝根证书序列号

        $request = new \AlipayFundTransToaccountTransferRequest();
        $content = [
            'out_biz_no'=>$order_code,
            'payee_type'=>'ALIPAY_LOGONID',
            'payee_account'=>$payee_account,
            'amount'=>$money,
            'payer_show_name'=>'',
            'payee_real_name'=>'',
            'remark'=>''
        ];
        $request->setBizContent(json_encode($content));
        $result = $aop->execute ($request);
        $responseNode = str_replace(".", "_", $request->getApiMethodName()) . "_response";
        $resultCode = $result->$responseNode->code;
        if ($resultCode == 10000){
            return true;
        }else{
            return false;
        }
    }

    /**
     * 获取支付宝授权用户ID
     * @param $auth_code
     * @return bool|mixed
     * @throws \Exception
     */
    public function getAuthToken($auth_code)
    {
        import('alipay.aop.AopClient');
        import('alipay.aop.request.AlipaySystemOauthTokenRequest');

        $aop = new \AopCertClient();
        $aop->gatewayUrl = 'https://openapi.alipay.com/gateway.do';
        $aop->appId = $this->app_id;
        $aop->rsaPrivateKeyFilePath = $this->private_key;
        $aop->signType = 'RSA2';
        $aop->isCheckAlipayPublicCert = true;
        $aop->alipayrsaPublicKey = $aop->getPublicKey($this->aliPayCertPath);
        $aop->appCertSN = $aop->getCertSN($this->appCertPath);//调用getCertSN获取证书序列号
        $aop->alipayRootCertSN = $aop->getRootCertSN($this->rootCertPath);//调用getRootCertSN获取支付宝根证书序列号

        $request = new \AlipaySystemOauthTokenRequest();
        $request->setGrantType("authorization_code");
        $request->setCode($auth_code);
        $result = $aop->execute($request);
        sp($result);die;
    }

    /**
     * 小程序支付接口
     * @param $body
     * @param $subject
     * @param $order_code
     * @param $money
     * @param $notify_url
     * @param $buyer_id
     * @return string
     */
    public function aliPayApplet($body, $subject, $order_code, $money, $notify_url, $buyer_id)
    {
        /**
         * 调用支付宝接口。
         */
        import('alipay.aop.AopCertClient');
        import('alipay.aop.request.AlipayTradeCreateRequest');

        $aop = new \AopCertClient();
        $aop->gatewayUrl = "https://openapi.alipay.com/gateway.do";
        $aop->appId = $this->applet_id;
        $aop->rsaPrivateKeyFilePath = $this->private_key;
        $aop->format = "json";
        $aop->postCharset = "UTF-8";
        $aop->signType = "RSA2";
        $aop->isCheckAlipayPublicCert = true;
        $aop->alipayrsaPublicKey = $aop->getPublicKey($this->aliPayCertPath);
        $aop->appCertSN = $aop->getCertSN($this->appletCertPath);//调用getCertSN获取证书序列号
        $aop->alipayRootCertSN = $aop->getRootCertSN($this->rootCertPath);//调用getRootCertSN获取支付宝根证书序列号

        $request = new \AlipayTradeCreateRequest();
        $content = [
            'body'=>$body,
            'subject'=>$subject,
            'out_trade_no'=>$order_code,
            'timeout_express'=>'30m',
            'total_amount'=>floatval($money),
            'buyer_id'=>$buyer_id,
        ];
        $request->setNotifyUrl($notify_url);
        $request->setBizContent(json_encode($content));
        $result = $aop->execute($request);
        $responseNode = str_replace(".", "_", $request->getApiMethodName()) . "_response";
        $resultCode = $result->$responseNode->code;
        if(!empty($resultCode) && $resultCode == 10000){
            return $result->$responseNode->trade_no;
        }
        return false;
    }

    // 支付宝授权参数
    public function get_auth()
    {
        $data = [
            'apiname'=>'com.alipay.account.auth',
            'method'=>'alipay.open.auth.sdk.code.get',
            'app_id'=>$this->applet_id,
            'app_name'=>'mc',
            'biz_type'=>'openservice',
            'pid'=>'2088421318174638',
            'product_id'=>'APP_FAST_LOGIN',
            'scope'=>'kuaijie',
            'target_id'=>md5(order_code() . uniqid()),
            'auth_type'=>'AUTHACCOUNT',
            'sign_type'=>'RSA2',
        ];
        ksort($data);
        import('alipay.aop.AopCertClient');
        $aop = new \AopClient();
        $aop->rsaPrivateKeyFilePath = $this->private_key;
        $aop->postCharset = "UTF-8";
        $sign =  urlencode($aop->generateSign($data, 'RSA2'));
        $data['sign'] = $sign;
        $data['contents'] = http_build_query($data);

        return $data;
    }
}